﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using System.IO;
using System.Reflection;
using NHibernate.Tool.hbm2ddl;
using NHibernate.Engine;
using System.Data;
using AsyncPersistence.Entities;
using NUnit.Framework;

namespace AsyncPersistenceTests
{
    [TestFixture]
    public class GenerateSchemaTool
    {
        #region Fields
        private ISessionFactory hsf;
        private Configuration hcfg;
        private const string localPath = @"..\..\..\AsyncPersistence";
        readonly string scriptsDirectoryDEV = Directory.GetCurrentDirectory() + "\\" + localPath + @"\";
        private const string STRUCTURE_FILENAME = "Structure.sql";
        #endregion

        #region Database generation tools
        [Test] 
        [Ignore]
        [Description("to generate database creation script")]
        public void GenerateSchemaDev()
        {
            hcfg = new Configuration();
            hcfg.Configure(scriptsDirectoryDEV+"hibernate.cfg.xml");
            DoScriptsGeneration(null, scriptsDirectoryDEV);
        }

        [Test]
        [Ignore]
        [Description("to execute database creation script")]
        public void GenerateLocalDatabase()
        {
            string[] fileList = { };
            GenerateLocalDb(fileList);
        }

        #endregion

        #region Helpers
        private void DoScriptsGeneration(IDbConnection dbConnection, string generationDir)
        {
            hcfg.AddAssembly(typeof(Client).Assembly);
            SchemaExport schemaExport = new SchemaExport(hcfg);
            string sctructureFilePath = generationDir + STRUCTURE_FILENAME;
            string tmpStructureFilePath = sctructureFilePath + ".tmp";

            TextWriter output = new StreamWriter(tmpStructureFilePath);
            schemaExport.Execute(true, !(dbConnection == null), false, dbConnection, output);

            StreamReader textFile = File.OpenText(tmpStructureFilePath);
            TextWriter readyToLaunchScript = new StreamWriter(sctructureFilePath);

            while (!textFile.EndOfStream)
            {
                string resultString = textFile.ReadLine() + ";";
                if (resultString.Trim().Length > 1)
                {
                    readyToLaunchScript.WriteLine(resultString);
                }
            }

            textFile.Close();
            readyToLaunchScript.Close();

            File.Delete(tmpStructureFilePath);
            Assert.True(true);
        }

        private void SetupConnection()
        {
            hcfg = new Configuration();
            try
            {
                hcfg.Configure(scriptsDirectoryDEV + "hibernate.cfg.xml");
                hcfg.AddAssembly(Assembly.GetCallingAssembly());
                hsf = hcfg.BuildSessionFactory();
            }

            catch (Exception ex)
            {                
                throw new HibernateException("Could not initialize session Testory", ex);
            }

        }

        private void GenerateLocalDb(IEnumerable<string> fileList)
        {

            SetupConnection();

            IDbConnection dbConnection = hsf.OpenSession().Connection;
            DoScriptsGeneration(dbConnection, scriptsDirectoryDEV);

            IStatelessSession session = hsf.OpenStatelessSession(dbConnection);

            foreach (string s in fileList)
            {
                Console.WriteLine("Start Processing script: " + s);
                string sqlQuery = File.OpenText(scriptsDirectoryDEV + s).ReadToEnd();

                string[] mutliQuery = sqlQuery.Split(';');

                foreach (string query in mutliQuery)
                {
                    Console.WriteLine("Processing line: " + query);
                    string execQuery = query.Replace("\r\n", string.Empty);

                    if (!string.IsNullOrEmpty(execQuery))
                    {
                        session.CreateSQLQuery(execQuery).ExecuteUpdate();
                    }
                }
            }
            session.Close();
        }
        #endregion
    }
}
